//////////////////////////////////////////////
// Hasher.h
//
//////////////////////////////////////////////

/// Defines / Macros -------------------------

#pragma once

/// Includes ---------------------------------

// nkMemory
#include <NilkinsMemory/Containers/String.h>
#include <NilkinsMemory/Containers/StringView.h>

// Standards
#include <functional>

/// Class ------------------------------------

namespace nkMaths
{
	class Hasher final
	{
		public :

			// Basic hashing function
			template <typename T>
			static unsigned long long hash (const T& element)
			{
				return (unsigned long long)std::hash<T>()(element) ;
			}

			static unsigned long long hash (const nkMemory::String& element)
			{
				return hash<std::string_view>(element) ;
			}

			static unsigned long long hash (const nkMemory::StringView& element)
			{
				return hash<std::string_view>(element) ;
			}

		public :

			// Combination
			static unsigned long long combineHashes (unsigned long long hash0, unsigned long long hash1)
			{
				return hash0 ^ (hash1 + 0x9e3779b9 + (hash0 << 6) + (hash0 >> 2)) ;
			}

			template <typename T, typename U>
			static unsigned long long hashAndCombine (const T& element0, const U& element1)
			{
				return combineHashes(hash(element0), hash(element1)) ;
			}

			template <typename T>
			static unsigned long long combineIntoHash (unsigned long long hash0, const T& element1)
			{
				return combineHashes(hash0, hash(element1)) ;
			}
	} ;
}